package com.geek.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;


@Service
public class IncrService {

    //过期时间秒
    private static final String EXPIRED_TIME="60";

    //窗口内限流数量
    private static final String WINDOW_TOTAL="2";

    private static String lockStr="if redis.call('EXISTS', KEYS[1]) == 0 " +//判断是否存在限流窗口
            "    then " +
            "        redis.call('set',KEYS[1],0,'nx','ex',ARGV[1]) " +//新建一个限流传播窗口
            "        return 1"+
            "    else " +
            "        if redis.call('INCR', KEYS[1]) < tonumber(ARGV[2]) " +//判断是否超过限流间隔
            "        then return 1" +
            "        else " +
            "        return 0"+
            " end "+
            "end";


   @Autowired
   private RedisTemplate redisTemplate;


    //使用固定窗口限流法实现限流
    //最显著的缺点就是两个窗口的间隔口的流量会出现双倍，从而失去限流意义
    public boolean incr(String key) {
        List<String> keys = Arrays.asList(key);

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(lockStr, Long.class);

        Long execute = (Long) redisTemplate.execute(redisScript, new StringRedisSerializer(), new StringRedisSerializer(),
                keys, EXPIRED_TIME, WINDOW_TOTAL);
        return execute == 1;
    }


}